import axios from 'axios';
import { ApiError } from '../utils/ApiError';
import { StatusCodes } from 'http-status-codes';

export interface ChatMessage {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

export interface ChatCompletionOptions {
  stream?: boolean;
  max_tokens?: number;
}

export interface Choice {
  index: number;
  message: {
    role: 'assistant';
    content: string;
    reasoning_content?: string;
  };
  finish_reason: 'stop' | 'length' | 'content_filter' | null;
}

export interface Usage {
  prompt_tokens: number;
  completion_tokens: number;
  total_tokens: number;
}

export interface ChatCompletionResponse {
  id: string;
  object: 'chat.completion';
  created: number;
  model: string;
  choices: Choice[];
  usage: Usage;
}

export class VolcanoApiError extends ApiError {
  constructor(statusCode: number, message: string, details?: any) {
    super(statusCode, message, details);
    Object.setPrototypeOf(this, VolcanoApiError.prototype);
    this.name = 'VolcanoApiError';
  }
}

export class VolcanoAI {
  private readonly apiKey: string;
  private readonly endpointId: string;
  private readonly baseURL = 'https://ark.cn-beijing.volces.com/api/v3';

  constructor(apiKey: string, endpointId: string) {
    if (!apiKey || !endpointId) {
      const error = new VolcanoApiError(
        StatusCodes.INTERNAL_SERVER_ERROR,
        'Missing required configuration',
        { apiKey: !apiKey, endpointId: !endpointId }
      );
      Object.setPrototypeOf(error, VolcanoApiError.prototype);
      throw error;
    }
    this.apiKey = apiKey;
    this.endpointId = endpointId;
  }

  private validateMessages(messages: ChatMessage[]): void {
    if (!Array.isArray(messages) || messages.length === 0) {
      throw new VolcanoApiError(
        StatusCodes.BAD_REQUEST,
        'Messages array must not be empty',
        { messages }
      );
    }

    for (const msg of messages) {
      if (!msg.role || !msg.content || !['system', 'user', 'assistant'].includes(msg.role)) {
        throw new VolcanoApiError(
          StatusCodes.BAD_REQUEST,
          'Invalid message format',
          { message: msg }
        );
      }
    }
  }

  async chatComplete(messages: ChatMessage[], options: ChatCompletionOptions = {}): Promise<ChatCompletionResponse> {
    try {
      this.validateMessages(messages);

      const response = await axios.post(
        `${this.baseURL}/chat/completions`,
        {
          model: this.endpointId,
          messages,
          stream: options.stream ?? false,
          max_tokens: options.max_tokens
        },
        {
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          timeout: 30000
        }
      );

      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error)) {
        const statusCode = error.response?.status || StatusCodes.INTERNAL_SERVER_ERROR;
        const volcanoError = new VolcanoApiError(
          statusCode,
          `火山引擎API调用失败: ${error.response?.data?.message || error.message}`,
          {
            errorCode: error.response?.data?.code,
            errorDetails: error.response?.data
          }
        );
        Object.setPrototypeOf(volcanoError, VolcanoApiError.prototype);
        throw volcanoError;
      }
      throw error;
    }
  }

  async streamChatComplete(
    messages: ChatMessage[],
    options: ChatCompletionOptions = {},
    onData: (content: string, reasoningContent?: string) => void
  ): Promise<void> {
    try {
      this.validateMessages(messages);

      const response = await axios.post(
        `${this.baseURL}/chat/completions`,
        {
          model: this.endpointId,
          messages,
          stream: true,
          max_tokens: options.max_tokens
        },
        {
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          responseType: 'stream',
          timeout: 60000
        }
      );

      for await (const chunk of response.data) {
        const lines = chunk.toString().split('\n').filter(Boolean);
        for (const line of lines) {
          if (line.startsWith('data: ')) {
            try {
              const data = JSON.parse(line.slice(6));
              if (data.choices?.[0]?.delta) {
                const { content, reasoning_content } = data.choices[0].delta;
                onData(content || '', reasoning_content);
              }
            } catch (parseError) {
              console.error('Failed to parse SSE data:', parseError);
            }
          }
        }
      }
    } catch (error) {
      if (axios.isAxiosError(error)) {
        const volcanoError = new VolcanoApiError(
          error.response?.status || StatusCodes.INTERNAL_SERVER_ERROR,
          `流式调用失败: ${error.response?.data?.message || error.message}`,
          {
            errorCode: error.response?.data?.code,
            errorDetails: error.response?.data
          }
        );
        Object.setPrototypeOf(volcanoError, VolcanoApiError.prototype);
        throw volcanoError;
      }
      throw error;
    }
  }

  async singleRoundChat(content: string, options: ChatCompletionOptions = {}): Promise<string> {
    const response = await this.chatComplete(
      [{ role: 'user', content }],
      options
    );
    return response.choices[0].message.content;
  }

  async systemChat(
    systemPrompt: string,
    userContent: string,
    options: ChatCompletionOptions = {}
  ): Promise<string> {
    const response = await this.chatComplete(
      [
        { role: 'system', content: systemPrompt },
        { role: 'user', content: userContent }
      ],
      options
    );
    return response.choices[0].message.content;
  }
}

export const createDefaultVolcanoAI = () => {
  const apiKey = process.env.ARK_API_KEY || '192561dc-f47b-416f-8a37-91ee60185d13';
  const endpointId = process.env.VOLCANO_ENDPOINT_ID || 'ep-20250209030436-7ld7h';
  return new VolcanoAI(apiKey, endpointId);
};
